package com.example.swaggerDemo.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.swaggerDemo.Dao.WxpayDao;
import com.example.swaggerDemo.entity.MsgEntity;
import com.example.swaggerDemo.util.*;
import org.apache.log4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@Resource
@Service
public class WxpayService implements WxpayDao {
    @Autowired
    private Environment env;
    private final org.apache.log4j.Logger logger = Logger.getLogger(this.getClass());

    public MsgEntity webPay(
            @RequestParam("title") String title,
            @RequestParam("openId") String openId,
            @RequestParam("ip") String ip,
            @RequestParam("notify_url") String notify_url,
            @RequestParam("money") String money,
            @RequestParam("orderId") String orderId
    ) {
        System.out.println("进入下单..");
        MsgEntity msg = new MsgEntity();
        System.out.println("进入下单..");

        String orderFee1 = money; //充值金额（单位：分）

        String paternerKey = env.getProperty("wxpay.key");
        String appId = env.getProperty("wxlog.appid");
        System.out.println("paternerKey"+paternerKey);
        System.out.println("orderFee1:"+orderFee1);

        try {
            // ---------------生成用户订单-----------------
            // ----- 统一下单参数------
            // 注意，参数的顺序不能错！！！！否则无法成功下单
            Map<String, String> paraMap = new HashMap<String, String>();
            paraMap.put("appid", appId);
            paraMap.put("body",  title+":"+orderId);
            paraMap.put("mch_id", env.getProperty("wxpay.mer_id"));
            paraMap.put("nonce_str", WXPayUtil.generateNonceStr());
            paraMap.put("openid", openId);
            paraMap.put("out_trade_no", orderId);//订单号
            paraMap.put("spbill_create_ip", ip);
            paraMap.put("total_fee", orderFee1);
            paraMap.put("trade_type", "JSAPI");
            paraMap.put("notify_url", notify_url);// 此路径是微信服务器调用支付结果通知路径
            String sign = WXPayUtil.generateSignature(paraMap, paternerKey);
            System.out.println("签名是" + sign);
            paraMap.put("sign", sign);

//            String xml = "<xml>" +
//                    "<appid>"+ appId +"</appid>"+
//                    "<body>"+ title+":"+orderId +"</body>"+
//                    "<mch_id>"+ env.getProperty("wxpay.mer_id") +"</mch_id>"+
//                    "<nonce_str>"+ WXPayUtil.generateNonceStr() +"</nonce_str>"+
//                    "<notify_url>"+ notify_url +"</notify_url>"+
//                    "<openid>"+ openId +"</openid>"+
//                    "<out_trade_no>"+ orderId +"</out_trade_no>"+
//                    "<spbill_create_ip>"+ ip +"</spbill_create_ip>"+
//                    "<total_fee>"+ orderFee1 + "" +"</total_fee>"+
//                    "<trade_type>JSAPI</trade_type>"+
//                    "<sign>"+ sign +"</sign>"+
//                    "</xml>";

            String xml = WXPayUtil.mapToXml(paraMap);//将所有参数(map)转xml格式
            //xml= new String(xml.getBytes("UTF-8"),"UTF-8");

            // 统一下单接口
            String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            //发送post请求"统一下单接口"返回预支付id:prepay_id
            System.out.println("xml入口是"+xml);
            String xmlStr = MyHttpUtils.doPost(unifiedorder_url, xml,Charset.forName("UTF-8").toString());
            System.out.println("xml出口"+xmlStr);
            //以下内容是返回前端页面的json数据
            String prepay_id = "";//预支付id
            if (xmlStr.indexOf("SUCCESS") != -1) {
                System.out.println("支付系统返回了prepay_id");
                Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
                prepay_id = map.get("prepay_id");
            } else {
                System.out.println("xmlStr"+xmlStr);
                System.out.println("prepay_id获取失败");
            }
            // =============至此已成功获取到prepay_id================
            //System.out.println("您的prepay_id的值是："+prepay_id);
            // 将“微信内H5调起支付”需要的参数打包成JSON，发给前端
            Map<String, String> payMap = new HashMap<String, String>();
            payMap.put("appId", appId);
            payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp() + "");
            payMap.put("nonceStr", WXPayUtil.generateNonceStr());
            payMap.put("signType", "MD5");
            payMap.put("package", "prepay_id=" + prepay_id);
            String paySign = WXPayUtil.generateSignature(payMap, paternerKey);
            payMap.put("paySign", paySign);
            if (payMap != null) {
                msg.setcode(true);
                msg.setobject(payMap);
                msg.setmsg("成功获得prepay_id，且将数据发送到前端");
            } else {
                msg.setcode(false);
                msg.setmsg("获取prepayId失败");
                msg.setobject("0");
            }
        } catch (Exception e) {
            msg.setcode(false);
            msg.setmsg("异常：" + e.toString());
            msg.setobject("000");
        }
        System.out.println(msg.getcode() + "...." + msg.getmsg() + "...." + msg.getobject());

        return msg;
    }



    /**
     * 方法名：getWxConfig</br>
     * 详述：获取微信的配置信息 </br>
     * @param
     * @return 说明返回值含义
     * @throws
     */
        public Map<String, String> getWxConfig(HttpServletRequest request, HttpServletResponse response) {
            response.setHeader("Access-Control-Allow-Origin", "*");

            Map<String, String> ret = new HashMap<>();
            //获取前台传来的三个参数
            String timestamp =  WXPayUtil.getCurrentTimestamp()+"";
            String nonce_str = WXPayUtil.generateNonceStr();
            String url = request.getParameter("url");
            logger.info("url"+url+"==============="+nonce_str+"============"+timestamp);

            //从缓存中读取token信息，如果没有则获取一个新的token，通过token获取ticket信息
            String access_token = (String)request.getSession().getAttribute("access_token");
            if(access_token == null) {
                /** 获取AccessToKen*/
                String getAccessToKen = "https://api.weixin.qq.com/cgi-bin/token?"
                        + "grant_type=client_credential&appid="+env.getProperty("wxlog.appid")+"&secret="+ env.getProperty("wxlog.appsecret");
                String  jsonObject = MyHttpUtils.doPost(getAccessToKen,"",Charset.forName("UTF-8").toString());

                JSONObject rq = JSON.parseObject(jsonObject);
                /**获取jsapi_ticket*/
                String getTicket = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+rq.get("access_token").toString()+"&type=jsapi";
                String rest = MyHttpUtils.doPost(getTicket,"",Charset.forName("UTF-8").toString());
                JSONObject re = JSON.parseObject(rest);
                /**将信息保存入缓存中*/
                request.getSession().setAttribute("token", rq.get("access_token").toString());
                request.getSession().setAttribute("ticket", re.get("ticket").toString());
            }
            /**生成签名*/
            String ticket = (String)request.getSession().getAttribute("ticket"); //微信返回的ticket
            String signature = shareUtil.getSignature(ticket,url,nonce_str,timestamp); //获取签名
            ret.put("appId", env.getProperty("wxlog.appid"));
            ret.put("nonceStr", nonce_str);
            ret.put("timestamp", timestamp);
            ret.put("signature", signature);
            return ret;
        }



    /**
     * 方法名：byteToHex</br>
     * 详述：字符串加密辅助方法 </br>
     * 开发人员：souvc  </br>
     * 创建时间：2016-1-5  </br>
     * @param hash
     * @return 说明返回值含义
     * @throws
     */
    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;

    }
}









